package cn.hg.solon.youcan.web.admin.controller.system;

import java.util.List;

import org.dromara.hutool.core.bean.BeanUtil;
import org.dromara.hutool.core.collection.ListUtil;
import org.dromara.hutool.core.convert.Convert;
import org.dromara.hutool.core.text.StrValidator;
import org.dromara.hutool.core.text.split.SplitUtil;
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.Mapping;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.MethodType;
import org.noear.solon.core.handle.ModelAndView;
import org.noear.solon.core.handle.Result;
import org.noear.solon.data.annotation.Cache;
import org.noear.solon.data.annotation.CacheRemove;
import org.noear.solon.validation.annotation.NotBlank;
import org.noear.solon.validation.annotation.NotEmpty;
import org.noear.solon.validation.annotation.NotNull;

import com.mybatisflex.core.paginate.Page;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hg.solon.youcan.common.annotation.Log;
import cn.hg.solon.youcan.common.constant.CacheConstants;
import cn.hg.solon.youcan.common.enums.BusinessType;
import cn.hg.solon.youcan.common.web.LayuiPage;
import cn.hg.solon.youcan.system.entity.SysRole;
import cn.hg.solon.youcan.system.service.SysDeptService;
import cn.hg.solon.youcan.system.service.SysPermissionService;
import cn.hg.solon.youcan.system.service.SysRoleService;
import cn.hg.solon.youcan.system.service.SysUserService;
import cn.hg.solon.youcan.web.admin.controller.BaseAdminController;
import cn.hg.solon.youcan.web.admin.controller.system.qo.RoleQueryObject;

/**
 * @author 胡高
 */
@Controller
@Mapping("/admin/system/role")
public class RoleController extends BaseAdminController {

    private static final String SERVICE_NAME = "系统角色";

    private static final String VIEW_PATH = "/admin/system/role/";

    @Inject
    private SysRoleService roleService;

    @Inject
    private SysPermissionService permissionService;

    @Inject
    private SysDeptService deptService;


    @Inject
    SysUserService userService;

    /**
     * 跳转到新增页面
     */
    @Mapping(path = "add", method = MethodType.GET)
    @SaCheckLogin
    public ModelAndView add(Context ctx) {
        this.log.info("跳转到新增[{}]页面", SERVICE_NAME);

        ModelAndView mav = new ModelAndView(VIEW_PATH + "add.html");

        return mav;
    }

    @Mapping(path = "add", method = MethodType.POST)
    @Log(title = SERVICE_NAME, businessType = BusinessType.CREATE)
    @SaCheckPermission(value = {"system:role:add"})
    @CacheRemove(tags = CacheConstants.SYS_ROLE_TAG)
    public Result<?> add(Context ctx, @NotNull SysRole bean, @NotNull String dataScope, String deptIds) {
        this.log.info("新增[{}]记录：bean={}", SERVICE_NAME, bean);

        this.roleService.save(bean);

        this.roleService.assignDataScope(bean, dataScope,
            StrValidator.isBlank(deptIds) ? ListUtil.empty()
                : Convert.toList(Integer.class, SplitUtil.split(deptIds, ",")));

        return Result.succeed();
    }

    @Mapping(path = "assignDataScope", method = MethodType.GET)
    @SaCheckLogin
    public ModelAndView assignDataScope(Context ctx, @NotNull Integer id) {
        this.log.info("跳转到[{}]分配数据权限页面：id={}", SERVICE_NAME, id);

        ModelAndView mav = new ModelAndView(VIEW_PATH + "assignDataScope.html");

        SysRole role = this.roleService.getById(id);
        mav.put("bean", role);

        return mav;
    }

    @Mapping(path = "assignPermission", method = MethodType.GET)
    @SaCheckLogin
    public ModelAndView assignPermission(Context ctx, @NotNull Integer id) {
        this.log.info("跳转到[{}]分配系统权限页面：id={}", SERVICE_NAME, id);

        ModelAndView mav = new ModelAndView(VIEW_PATH + "assignPermission.html");

        SysRole role = this.roleService.getById(id);
        mav.put("bean", role);

        return mav;
    }

    @Mapping(path = "delete", method = MethodType.DELETE)
    @Log(title = SERVICE_NAME, businessType = BusinessType.DELETE)
    @SaCheckPermission(value = {"system:role:del"})
    @CacheRemove(tags = CacheConstants.SYS_ROLE_TAG)
    public Result<?> delete(Context ctx, @NotEmpty String ids) {
        this.log.info("删除[{}]记录：ids={}", SERVICE_NAME, ids);

        List<Integer> idList = StrValidator.isBlank(ids) ? ListUtil.empty() : Convert.toList(Integer.class, SplitUtil.split(ids, ","));

        return this.roleService.removeByIds(idList) ? Result.succeed() : Result.failure();
    }

    /**
     * 跳转到记录展示页面
     */
    @Mapping(path = "detail", method = MethodType.GET)
    @SaCheckPermission(value = {"system:role:query"})
    public ModelAndView detail(Context ctx, int id) {
        this.log.info("跳转到[{}]展示页面：id={}", SERVICE_NAME, id);

        ModelAndView mav = new ModelAndView(VIEW_PATH + "detail.html");

        mav.put("bean", this.roleService.getById(id));

        return mav;
    }

    @Mapping(path = "doAssignDataScope", method = MethodType.PUT)
    @Log(title = "分配数据权限", businessType = BusinessType.GRANT)
    @SaCheckPermission(value = {"system:role:assignDataScope"})
    @CacheRemove(tags = CacheConstants.SYS_ROLE_TAG + "," + CacheConstants.SYS_DEPT_TAG)
    public Result<?> doAssignDataScope(Context ctx, @NotNull Integer id, @NotNull String dataScope, String deptIds) {
        this.log.info("执行[{}]分配数据权限操作：id={}, deptIds={}", SERVICE_NAME, id, deptIds);

        SysRole role = this.roleService.getById(id);

        this.roleService.assignDataScope(role, dataScope,
            StrValidator.isBlank(deptIds) ? ListUtil.empty()
                : Convert.toList(Integer.class, SplitUtil.split(deptIds, ",")));

        return Result.succeed();
    }

    @Mapping(path = "doAssignPermission", method = MethodType.PUT)
    @Log(title = "分配权限", businessType = BusinessType.GRANT)
    @SaCheckPermission(value = {"system:role:assignPermission"})
    @CacheRemove(tags = CacheConstants.SYS_ROLE_TAG + "," + CacheConstants.SYS_PERMISSION_TAG)
    public Result<?> doAssignPermission(Context ctx, @NotNull Integer id, @NotBlank String permissionIds) {
        this.log.info("执行[{}]分配权限操作：id={}, permissionIds={}", SERVICE_NAME, id, permissionIds);
        SysRole role = this.roleService.getById(id);

        this.roleService.assignPermission(role,
            StrValidator.isBlank(permissionIds) ? ListUtil.empty()
                : Convert.toList(Integer.class, SplitUtil.split(permissionIds, ",")));

        return Result.succeed();
    }

    /**
     * 跳转到编辑页面
     */
    @Mapping(path = "edit", method = MethodType.GET)
    @SaCheckLogin
    public ModelAndView edit(Context ctx, int id) {
        this.log.info("跳转到编辑[{}]页面", SERVICE_NAME);

        ModelAndView mav = new ModelAndView(VIEW_PATH + "edit.html");

        SysRole role = this.roleService.getById(id);
        mav.put("bean", role);
        mav.put("depts", this.deptService.listByRole(role));

        return mav;
    }

    @Mapping(path = "edit", method = MethodType.PUT)
    @Log(title = SERVICE_NAME, businessType = BusinessType.UPDATE)
    @SaCheckPermission(value = {"system:role:edit"})
    @CacheRemove(tags = CacheConstants.SYS_ROLE_TAG + "," + CacheConstants.SYS_DEPT_TAG)
    public Result<?> edit(Context ctx, @NotNull SysRole bean, @NotNull String dataScope, String deptIds) {
        this.log.info("更新[{}]记录：bean={}, dataScope={}, deptIds={}", SERVICE_NAME, bean, dataScope, deptIds);

        this.roleService.assignDataScope(bean, dataScope,
            StrValidator.isBlank(deptIds) ? ListUtil.empty()
                : Convert.toList(Integer.class, SplitUtil.split(deptIds, ",")));

        // 更新到数据库
        return this.roleService.update(bean) ? Result.succeed() : Result.failure();
    }

    @Mapping(path = "", method = MethodType.GET)
    @SaCheckLogin
    public ModelAndView index(Context ctx) {
        this.log.info("跳转到[{}]列表页面", SERVICE_NAME);

        ModelAndView mav = new ModelAndView(VIEW_PATH + "index.html");

        mav.putAll(ctx.paramMap());

        return mav;
    }

    /**
     * 分页查询功能
     */
    @Mapping(path = "query", method = MethodType.POST)
    @SaCheckPermission(value = {"system:role:query"})
    @Cache(key = CacheConstants.SYS_ROLE_KEY + ":query:${query}", tags = CacheConstants.SYS_ROLE_TAG , seconds = CacheConstants.CACHE_SECONDS_ONE_HOUR)
    public LayuiPage<SysRole> query(Context ctx, @NotNull RoleQueryObject query) {
        this.log.info("执行[{}]分页查询：query={}", SERVICE_NAME, query);

        /*
         * 服务调用
         */
        Page<SysRole> result =
            this.roleService.pageByMap(new Page<>(query.getPageNumber(), query.getPageSize()), query.toMap());

        /*
         * 返回值处理
         */
        return new LayuiPage<>(result.getRecords(), result.getTotalRow());
    }

    @Mapping(path = "queryByUser", method = MethodType.GET)
    @SaCheckLogin
    @Cache(key = CacheConstants.SYS_ROLE_KEY + ":queryByUser:${userId}", tags = CacheConstants.SYS_ROLE_TAG , seconds = CacheConstants.CACHE_SECONDS_ONE_HOUR)
    public List<SysRole> queryByUser(Context ctx, @NotNull Integer userId){
        this.log.info("执行[{}]查询：userId={}", SERVICE_NAME, userId);

        return this.roleService.listByUser(this.userService.getById(userId));
    }

    @Mapping(path = "queryList", method = MethodType.POST)
    @SaCheckLogin
    @Cache(key = CacheConstants.SYS_ROLE_KEY + ":queryList:${query}", tags = CacheConstants.SYS_ROLE_TAG , seconds = CacheConstants.CACHE_SECONDS_ONE_HOUR)
    public List<SysRole> queryList(Context ctx, @NotNull RoleQueryObject query){
        this.log.info("执行[{}]查询：query={}", SERVICE_NAME, query);
        return this.roleService.listByMap(BeanUtil.beanToMap(query));
    }

}
